#ifndef __SMART_POINTER_H__
  #define __SMART_POINTER_H__

#include "exceptions.h"
#include "global_variables.h"

//! Smart pointer implementation

/*!
A simple implementation for smart pointers (like std::auto_ptr). Allocated memory will be deleted automatically
when the smart_pointer goes out of scope.

Implementation date: 2007

Usage:

\code
smart_pointer<int> sp = new int();
*sp = 17;
\endcode
*/

template <class T>
class smart_pointer {
private:
  T *obj;

  //! assignment operator: not allowed
  smart_pointer &operator=(const smart_pointer &sp);

  //! copy constructor: not allowed
  smart_pointer(const smart_pointer &sp);

public:
  //! sets the internal pointer to null without destructing the object (the same as auto_ptr::release)
  /*!
  be careful!
  this is only useful if you want to take back the ownership of the pointer, which means you want to delete the
  pointer yourself.
  call operator->() before calling release() and save its return value to a temp variable.
  do not forget to call:
  delete temp;
  */
  void release() {
    obj = 0;
  } // release

  //! deletes the content of the smart_pointer and sets it to null
  void clear() {
    delete obj;
    obj = 0;
  } // clear

  //! returns true if the content is not set yet or if it is cleared
  bool is_null() const {
    return (obj == 0);
  } // is_null

  //! returns the content of the smart_pointer as a pointer (may throw an exception)
  T *operator->() const {
    if (obj == 0)
      throw pointer_exception(global_empty_string);

    return obj;
  } // operator->

  //! returns the content of the smart_pointer (may throw an exception)
  T &operator*() const {
    if (obj == 0)
      throw pointer_exception(global_empty_string);

    return *obj;
  } // operator*

  //! assignment operator: the content will be deleted first, thw ownership of the given pointer will be transferred to the smart_pointer
  void operator=(T *t) {
    clear();
    obj = t;
  } // operator=

  //! default constructor: set the content to null
  smart_pointer() : obj(0) {
    // nothing to do
  } // smart_pointer

  //! constructor
  smart_pointer(T *t) : obj(t) {
    // nothing to do
  } // smart_pointer

  //! destructor: deletes the allocated memory
  virtual ~smart_pointer() {
    clear();
  } // ~smart_pointer
}; // class smart_pointer

#endif
